#include "spectrumwidget.h"
#include <QPainter>
#include <QLinearGradient>
#include <cmath>

SpectrumWidget::SpectrumWidget(QWidget *parent)
    : QWidget(parent)
    , m_numBands(20)
{
    m_spectrum.resize(m_numBands);
    m_targetSpectrum.resize(m_numBands);
    m_spectrum.fill(0.0f);
    m_targetSpectrum.fill(0.0f);

    setMinimumSize(800, 400);
    setAttribute(Qt::WA_OpaquePaintEvent);
    
    // Set dark background
    QPalette pal = palette();
    pal.setColor(QPalette::Window, QColor(20, 20, 20));
    setAutoFillBackground(true);
    setPalette(pal);

    // Animation timer for smooth transitions
    m_animationTimer = new QTimer(this);
    connect(m_animationTimer, &QTimer::timeout, this, &SpectrumWidget::onAnimationTimer);
    m_animationTimer->start(16); // ~60 FPS
}

void SpectrumWidget::setNumBands(int numBands)
{
    m_numBands = numBands;
    m_spectrum.resize(m_numBands);
    m_targetSpectrum.resize(m_numBands);
    m_spectrum.fill(0.0f);
    m_targetSpectrum.fill(0.0f);
}

void SpectrumWidget::updateSpectrum(const QVector<float> &spectrum)
{
    if (spectrum.size() != m_numBands) {
        return;
    }
    m_targetSpectrum = spectrum;
}

void SpectrumWidget::onAnimationTimer()
{
    smoothTransition();
    update();
}

void SpectrumWidget::smoothTransition()
{
    // Smooth interpolation between current and target values
    const float fallSpeed = 0.3f;   // How fast bars fall
    const float riseSpeed = 0.5f;   // How fast bars rise
    
    for (int i = 0; i < m_numBands; i++) {
        float diff = m_targetSpectrum[i] - m_spectrum[i];
        
        if (diff > 0) {
            // Rising - faster response
            m_spectrum[i] += diff * riseSpeed;
        } else {
            // Falling - slower response for nice decay effect
            m_spectrum[i] += diff * fallSpeed;
        }
    }
}

QColor SpectrumWidget::getGradientColor(float value) const
{
    // Create green to yellow to red gradient
    // value should be between 0 and 1
    value = qMax(0.0f, qMin(1.0f, value));
    
    if (value < 0.5f) {
        // Green to Yellow
        float t = value * 2.0f;
        int r = static_cast<int>(t * 255);
        int g = 255;
        int b = 0;
        return QColor(r, g, b);
    } else {
        // Yellow to Red
        float t = (value - 0.5f) * 2.0f;
        int r = 255;
        int g = static_cast<int>((1.0f - t) * 255);
        int b = 0;
        return QColor(r, g, b);
    }
}

void SpectrumWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    
    // Draw background
    painter.fillRect(rect(), QColor(20, 20, 20));
    
    if (m_numBands == 0) {
        return;
    }
    
    int width = this->width();
    int height = this->height();
    
    // Calculate bar dimensions
    int margin = 10;
    int spacing = 4;
    int totalSpacing = spacing * (m_numBands - 1) + margin * 2;
    int barWidth = (width - totalSpacing) / m_numBands;
    
    // Draw spectrum bars
    for (int i = 0; i < m_numBands; i++) {
        float value = m_spectrum[i];
        
        int x = margin + i * (barWidth + spacing);
        int barHeight = static_cast<int>(value * (height - 2 * margin));
        int y = height - margin - barHeight;
        
        // Create gradient for this bar
        QLinearGradient gradient(x, y + barHeight, x, y);
        
        // Bottom color (green)
        gradient.setColorAt(0.0, QColor(0, 255, 0));
        
        // Middle color (yellow)
        gradient.setColorAt(0.5, QColor(255, 255, 0));
        
        // Top color based on value
        if (value > 0.7f) {
            gradient.setColorAt(1.0, QColor(255, 0, 0)); // Red for high values
        } else {
            gradient.setColorAt(1.0, QColor(255, 255, 0)); // Yellow
        }
        
        painter.setBrush(gradient);
        painter.setPen(Qt::NoPen);
        
        // Draw rounded rectangle
        painter.drawRoundedRect(x, y, barWidth, barHeight, 2, 2);
        
        // Draw subtle outline
        painter.setPen(QPen(QColor(0, 0, 0, 100), 1));
        painter.setBrush(Qt::NoBrush);
        painter.drawRoundedRect(x, y, barWidth, barHeight, 2, 2);
    }
    
    // Draw frequency labels
    painter.setPen(QColor(150, 150, 150));
    QFont font = painter.font();
    font.setPixelSize(10);
    painter.setFont(font);
    
    // Draw a few frequency markers
    QStringList labels = {"20", "50", "100", "200", "500", "1K", "2K", "5K", "10K", "20K"};
    int labelStep = m_numBands / (labels.size() - 1);
    
    for (int i = 0; i < labels.size() && i * labelStep < m_numBands; i++) {
        int barIndex = i * labelStep;
        if (barIndex >= m_numBands) barIndex = m_numBands - 1;
        
        int x = margin + barIndex * (barWidth + spacing);
        painter.drawText(x, height - 2, labels[i]);
    }
    
    // Draw title
    font.setPixelSize(16);
    font.setBold(true);
    painter.setFont(font);
    painter.setPen(QColor(200, 200, 200));
    painter.drawText(margin, 25, "Audio Spectrum Analyzer (0Hz - 20kHz)");
}